﻿namespace MicroCloud.Identity
{
    /// <summary>
    /// 业务实现：身份认证模块
    /// </summary>
    public partial class IdentityService
    {
        #region "属性"
        #region "获取 用户角色信息查询数据集"
        /// <summary>
        /// 获取 用户角色信息查询数据集
        /// </summary>
        public IQueryable<UserRole> UserRoles
        {
            get { return UserRoleRepository.QueryAsNoTracking(); }
        }
        #endregion
        #region "获取 角色用户仓储"
        /// <summary>
        /// 获取 角色用户仓储
        /// </summary>
        protected IRoleUserStore<Role> RoleUserStore => _provider.GetService<IRoleUserStore<Role>>();
        #endregion

        #endregion

        #region "方法"
        #region "检查用户角色信息信息是否存在"
        /// <summary>
        /// 检查用户角色信息信息是否存在
        /// </summary>
        /// <param name="predicate">检查谓语表达式</param>
        /// <param name="id">更新的用户角色信息编号</param>
        /// <returns>用户角色信息是否存在</returns>
        public async Task<bool> CheckUserRoleExists(Expression<Func<UserRole, bool>> predicate, long id = default)
        {
            return await UserRoleRepository.CheckExistsAsync(predicate, id);
        }
        #endregion
        #region "更新用户角色信息"
        /// <summary>
        /// 更新用户角色信息
        /// </summary>
        /// <param name="dtos">用户角色信息集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateUserRoles(params UserRoleInputDto[] dtos)
        {
            Check.Validate<UserRoleInputDto, long>(dtos, nameof(dtos));

            var userIds = new List<string>();
            OperationResult result = await UserRoleRepository.UpdateAsync(dtos,
                (dto, entity) =>
                {
                    string userId = UserRoleRepository.QueryAsNoTracking(m => m.UserId == entity.UserId).Select(m => m.User.Id.ToString()).FirstOrDefault();
                    userIds.AddIfNotNull(userId);
                    return Task.FromResult(0);
                });
            if (result.Succeeded && userIds.Count > 0)
            {
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = userIds.ToArray() };
                await EventBus.PublishAsync(eventData);
            }
            return result;
        }
        #endregion
        #region "删除用户角色信息"
        /// <summary>
        /// 删除用户角色信息
        /// </summary>
        /// <param name="ids">用户角色信息编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> DeleteUserRoles(params long[] ids)
        {
            var userIds = new List<string>();
            OperationResult result = await UserRoleRepository.DeleteAsync(ids,
                (entity) =>
                {
                    string userId = UserRoleRepository.QueryAsNoTracking(m => m.UserId == entity.UserId).Select(m => m.User.Id.ToString()).FirstOrDefault();
                    userIds.AddIfNotNull(userId);
                    return Task.FromResult(0);
                });
            if (result.Succeeded && userIds.Count > 0)
            {
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = userIds.ToArray() };
                await EventBus.PublishAsync(eventData);
            }

            return result;
        }
        #endregion
        #region "设置用户的角色"
        /// <summary>
        /// 设置用户的角色
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <param name="roleIds">角色编号集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> SetUserRoles(long userId, params long[] roleIds)
        {
            User user = await UserManager.FindByIdAsync(userId.ToString());
            if (user == null)
            {
                return OperationResult.Error(I18N.T("用户 {0} 不存在", userId));
            }
            IList<string> roleNames = RoleManager.Roles.Where(m => roleIds.Contains(m.Id)).Select(m => m.Name).ToList();
            IList<string> existRoleNames = await UserManager.GetRolesAsync(user);
            string[] addRoleNames = roleNames.Except(existRoleNames).ToArray();
            string[] removeRoleNames = existRoleNames.Except(roleNames).ToArray();

            if (!addRoleNames.Union(removeRoleNames).Any())
            {
                return OperationResult.Success();
            }

            try
            {
                IdentityResult result = await UserManager.AddToRolesAsync(user, addRoleNames);
                if (!result.Succeeded)
                {
                    return result.ToOperationResult();
                }
                result = await UserManager.RemoveFromRolesAsync(user, removeRoleNames);
                if (!result.Succeeded)
                {
                    return result.ToOperationResult();
                }
                await UserManager.UpdateSecurityStampAsync(user);

                //更新用户缓存使角色生效
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = new[] { user.Id.ToString() } };
                await EventBus.PublishAsync(eventData);
            }
            catch (InvalidOperationException ex)
            {
                return OperationResult.Error(ex.Message);
            }

            if (addRoleNames.Length > 0 && removeRoleNames.Length == 0)
            {
                return OperationResult.Success(I18N.T("用户 {0} 添加角色 {1} 成功", user.UserName, addRoleNames.ExpandAndToString()));
            }
            if (addRoleNames.Length == 0 && removeRoleNames.Length > 0)
            {
                return OperationResult.Success(I18N.T("用户 {0} 移除角色 {1} 成功", user.UserName, removeRoleNames.ExpandAndToString()));
            }
            return OperationResult.Success(I18N.T("用户 {0} 添加角色 {1} 、移除角色 {2} 成功。", user.UserName, addRoleNames.ExpandAndToString(), removeRoleNames.ExpandAndToString()));
        }
        #endregion
        #region "设置角色的用户"
        /// <summary>
        /// 设置角色的用户
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <param name="userIds">用户编号集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> SetRoleUsers(long roleId, params long[] userIds)
        {
            Role role = await RoleManager.FindByIdAsync(roleId.ToString());
            if (role == null)
            {
                return OperationResult.Error(I18N.T("角色 {0} 不存在", roleId));
            }
            IList<string> dbUserIds = UserManager.Users.Where(m => userIds.Contains(m.Id)).Select(m => m.Id.ToString()).ToList();
            IList<string> existUserIds = await RoleUserStore.GetUsersAsync(role);
            string[] addUserIds = dbUserIds.Except(existUserIds).ToArray();
            string[] removeUserIds = existUserIds.Except(dbUserIds).ToArray();

            if (!addUserIds.Union(removeUserIds).Any())
            {
                return OperationResult.Success();
            }

            try
            {
                var result = await RoleUserStore.AddToUsersAsync(role, addUserIds);
                if (!result.Succeeded)
                {
                    return result;
                }
                foreach (var addUserId in addUserIds)
                {
                    User user = await UserManager.FindByIdAsync(addUserId);
                    if (user == null)
                    {
                        return OperationResult.Error(I18N.T("用户 {0} 不存在", addUserId));
                    }
                    await UserManager.UpdateSecurityStampAsync(user);
                }

                result = await RoleUserStore.RemoveFromUsersAsync(role, removeUserIds);
                if (!result.Succeeded)
                {
                    return result;
                }
                foreach (var removeUserId in removeUserIds)
                {
                    User user = await UserManager.FindByIdAsync(removeUserId);
                    if (user != null)
                    {
                        await UserManager.UpdateSecurityStampAsync(user);
                    }
                }

                //更新用户缓存使角色生效
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = addUserIds.Union(removeUserIds).ToArray() };
                await EventBus.PublishAsync(eventData);

            }
            catch (InvalidOperationException ex)
            {
                return OperationResult.Error(ex.Message);
            }

            if (addUserIds.Length > 0 && removeUserIds.Length == 0)
            {
                return OperationResult.Success(I18N.T("角色 {0} 添加用户 {1} 成功", role.Name, addUserIds.ExpandAndToString()));
            }
            if (addUserIds.Length == 0 && removeUserIds.Length > 0)
            {
                return OperationResult.Success(I18N.T("角色 {0} 移除用户 {1} 成功", role.Name, removeUserIds.ExpandAndToString()));
            }
            return OperationResult.Success(I18N.T("角色 {0} 添加用户 {1} 、移除用户 {2} 成功。", role.Name, addUserIds.ExpandAndToString(), removeUserIds.ExpandAndToString()));
        }
        #endregion

        #endregion

    }

}
